package com.tianji.learning.service.impl;

import com.tianji.api.client.course.CourseClient;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.leanring.LearningLessonDTO;
import com.tianji.api.dto.leanring.LearningRecordDTO;
import com.tianji.common.autoconfigure.mq.RabbitMqHelper;
import com.tianji.common.constants.MqConstants;
import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.exceptions.DbException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.po.LearningLesson;
import com.tianji.learning.domain.po.LearningRecord;
import com.tianji.learning.domain.dto.LearningRecordFormDTO;
import com.tianji.learning.enums.LessonStatus;
import com.tianji.learning.enums.SectionType;
import com.tianji.learning.mapper.LearningRecordMapper;
import com.tianji.learning.redis.RedisCacheTemplate;
import com.tianji.learning.service.ILearningLessonService;
import com.tianji.learning.service.ILearningRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 学习记录表 服务实现类
 * </p>
 *
 * @author lcm
 * @since 2023-07-22
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class LearningRecordServiceImpl extends ServiceImpl<LearningRecordMapper, LearningRecord> implements ILearningRecordService {

    private final ILearningLessonService iLearningLessonService;
    private final RabbitMqHelper rabbitMqHelper;
    private final RedisCacheTemplate redisCacheTemplate;
    private final CourseClient courseClient;
    private final RabbitMqHelper mqHelper;





    @Override
    public LearningLessonDTO getLearningRecordById(Long courseId) {

        //1.获取用户id
        Long userId = UserContext.getUser();
        //2.获取对应课表
        LearningLesson lesson = iLearningLessonService.lambdaQuery()
                .eq(LearningLesson::getUserId, userId)
                .eq(LearningLesson::getCourseId, courseId)
                .one();

        if(lesson ==null){
            return null;
        }

        //3.拷贝课表信息至DTO
        LearningLessonDTO learningLessonDTO = BeanUtils.copyBean(lesson, LearningLessonDTO.class);
        //4.获取学习过的小节记录

        List<LearningRecord> records = lambdaQuery()
                .eq(LearningRecord::getLessonId, learningLessonDTO.getId())
                .eq(LearningRecord::getUserId, userId)
                .list();
        List<LearningRecordDTO> recordDTOList = new ArrayList<>();
        for (LearningRecord record : records) {
            LearningRecordDTO learningRecordDTO = BeanUtils.copyBean(record, LearningRecordDTO.class);
            recordDTOList.add(learningRecordDTO);
        }
        //5.封装DTO
        learningLessonDTO.setRecords(recordDTOList);

        return learningLessonDTO;
    }

    @Override
    @Transactional
    public void commitRecord(LearningRecordFormDTO learningRecordFormDTO) {
        //1.获取用户id
        Long userId = UserContext.getUser();
        //2.判断学习记录类型
        boolean handle;
        if(learningRecordFormDTO.getSectionType() == SectionType.VIDEO){
            //如果章节类型是视频
            handle = handleVideo(learningRecordFormDTO, userId);
        }
        else {
            //如果章节类型是考试
            handle = handleExam(learningRecordFormDTO, userId);
        }
        if(!handle){
            //如果小节没有学完，则无法更新课表进度
            return;
        }
        //3.处理课表
        handleLesson(learningRecordFormDTO);

    }

    private boolean handleVideo(LearningRecordFormDTO learningRecordFormDTO, Long userId) {
        boolean finished=false;
        //2.1判断是否是第一次学习
        //查询redis中是否存在数据
        LearningRecord record = redisCacheTemplate.redisCacheQueryRecord(learningRecordFormDTO.getLessonId(),learningRecordFormDTO.getSectionId());
        //如果缓存中不存在，就查询数据库
        if(record == null){
            record = lambdaQuery()
                    .eq(LearningRecord::getUserId, userId)
                    .eq(LearningRecord::getLessonId, learningRecordFormDTO.getLessonId())
                    .eq(LearningRecord::getSectionId, learningRecordFormDTO.getSectionId())
                    .one();

            if(record!=null){
                //同时写入缓存
                redisCacheTemplate.redisCacheWriteRecord(record);
            }
        }



        //2.1.1 是，新增记录
        if(record == null){
            record = BeanUtils.copyBean(learningRecordFormDTO, LearningRecord.class);
            record.setUserId(userId);
            record.setCreateTime(learningRecordFormDTO.getCommitTime());
            record.setUpdateTime(learningRecordFormDTO.getCommitTime());
            boolean success = save(record);
            if(!success){
                throw new DbException("新增学习记录失败！");
            }
        }
        //2.1.2 否，更新记录
        else {
            //2.2.1 判断是否学完，否则更新课表最近学习小节
            record.setMoment(learningRecordFormDTO.getMoment());
            boolean first=!record.getFinished()&&learningRecordFormDTO.getMoment()*2>learningRecordFormDTO.getDuration();
            if (first) {
                record.setFinished(true);
                record.setFinishTime(learningRecordFormDTO.getCommitTime());
                finished = true;
                //2.2.2 更新课表最近学习时间
                record.setUpdateTime(learningRecordFormDTO.getCommitTime());
                boolean update = updateById(record);
                if (!update) {
                    throw new DbException("更新学习记录失败！");
                }
                //发送MQ消息至积分服务
                mqHelper.send(
                        MqConstants.Exchange.LEARNING_EXCHANGE,
                        MqConstants.Key.LEARN_SECTION,
                        userId
                );
                log.info("用户：{}向积分服务发送，课程小节学习一小节",userId);

                //清理缓存
                redisCacheTemplate.cleanCache(learningRecordFormDTO.getLessonId(),learningRecordFormDTO.getSectionId());
            }
            else {
                LearningRecord record1 = new LearningRecord();
                record1.setLessonId(learningRecordFormDTO.getLessonId());
                record1.setSectionId(learningRecordFormDTO.getSectionId());
                record1.setMoment(learningRecordFormDTO.getMoment());
                record1.setId(record.getId());
                record1.setFinished(record.getFinished());
                //更新缓存
                redisCacheTemplate.redisCacheWriteRecord(record1);
                log.debug("不是第一次学完，更新缓存学习记录");
                //同时发布mq异步延迟任务
                rabbitMqHelper.sendDelayMessage(
                        MqConstants.Exchange.REDIS_DELAY_EXCHANGE,
                        MqConstants.Key.REDIS_DELAY_KEY,
                        record1,
                        Duration.ofMinutes(20)
                );
                log.debug("发送消息成功");

            }
        }
        return finished;
    }

    private boolean handleExam(LearningRecordFormDTO learningRecordFormDTO, Long userId) {
        //2.3 新增学习记录
        LearningRecord record = BeanUtils.copyBean(learningRecordFormDTO, LearningRecord.class);
        record.setUserId(userId);
        record.setFinished(true);
        record.setCreateTime(learningRecordFormDTO.getCommitTime());
        record.setUpdateTime(learningRecordFormDTO.getCommitTime());
        updateById(record);
        return true;
    }

    private void handleLesson(LearningRecordFormDTO learningRecordFormDTO) {
        LearningLesson lesson = iLearningLessonService.lambdaQuery()
                .eq(LearningLesson::getId, learningRecordFormDTO.getLessonId())
                .one();
        if(lesson == null){
            throw new BizIllegalException("课表不存在，无法更新数据！");
        }
        boolean allLearned=false;

        //3.判断是否学完全部小节
        CourseFullInfoDTO courseInfoById = courseClient.getCourseInfoById(lesson.getCourseId(), false, false);
        if (courseInfoById == null) {
            throw new BizIllegalException("课程不存在，无法更新数据！");
        }
        allLearned = courseInfoById.getSectionNum() <= lesson.getLearnedSections();

        //更新课表
        iLearningLessonService.lambdaUpdate()
                .set(lesson.getLearnedSections() == 0,LearningLesson::getStatus,LessonStatus.LEARNING.getValue())//如果章节为零，修改课表状态为学习中
                .set(allLearned,LearningLesson::getStatus,LessonStatus.FINISHED.getValue())
                .set(allLearned,LearningLesson::getLatestLearnTime,learningRecordFormDTO.getCommitTime())
                .set(allLearned,LearningLesson::getLatestSectionId,learningRecordFormDTO.getSectionId())
                .setSql("learned_sections = learned_sections + 1")
                .eq(LearningLesson::getId,lesson.getId())
                .update();

    }


}
